use syn::{Lit, Type, MetaNameValue, Attribute, Meta, MetaList, NestedMeta};

/// 获取属性值
///
/// # 参数说明
///
/// * attrs Derive的属性列表
/// * key 要获取的属性名称
pub fn get_attribute_value(ast: &syn::DeriveInput, key: &str) -> String {
    let attrs: Vec<_> = ast
        .attrs
        .iter()
        .map(|attr| {
            let name = attr.path.get_ident().unwrap().to_string();
            let meta = attr.parse_meta();
            let value = match meta {
                Ok(meta) => {
                    if let syn::Meta::NameValue(MetaNameValue { lit, .. }) = meta {
                        match lit {
                            syn::Lit::Str(s) => s.value(),
                            _ => panic!("属性设置错误,输入为字符串"),
                        }
                    } else {
                        panic!("属性设置错误,输入为字符串")
                    }
                }
                Err(_) => panic!("属性设置错误"),
            };
            (name, value)
        })
        .collect();
    let mut r = "".to_string();
    for (name,value) in attrs {
        if name == key {
            r = value.clone();
        }
    }
    r
}

pub fn get_column_attribute_value(attrs: &Vec<Attribute>, key: &str) -> String {
    let mut r = "".to_string();
    for attr in attrs{
        if attr.path.is_ident("column"){
            let meta = attr.parse_meta().expect("column|column_field:转换属性为meta");
            let v = get_value_from_meta(&meta, key);
            if v != None{
                r = v.unwrap();
            }
        }
    };
    r
}

fn get_value_from_meta(meta: &Meta, key: &str) -> Option<String> {
    if let Meta::List(MetaList { nested, .. }) = meta {
        nested.iter().find_map(|nested_meta| match nested_meta {
            NestedMeta::Meta(Meta::NameValue(MetaNameValue {
                path,
                lit: Lit::Str(lit_str),
                ..
            })) if path.is_ident(key) => Some(lit_str.value()),
            _ => None,
        })
    } else {
        None
    }
}

/// 根据属性值生成TinyDBMeta的各字段内容
///
/// # 参数说明
///
/// * attrs Derive的属性列表
/// * struct_name 对应结构体名称
pub fn get_table_name(ast: &syn::DeriveInput) -> String {
    let struct_name = &ast.ident;
    let mut table_name = String::new();
    for (i, ch) in struct_name.to_string().char_indices() {
        if i > 0 && ch.is_uppercase() {
            table_name.push('_');
        }
        table_name.push(ch.to_ascii_lowercase());
    }
    table_name
}


/// 将 Rust 类型转换为 MySQL 数据库类型
pub fn rust_type_to_dbtype(rust_type: &Type) -> String {
    let mut r = String::new();
    let s = match rust_type {
        Type::Path(type_path) => {
            if let Some(segment) = type_path.path.segments.first() {
                r = segment.ident.to_string();
            }
            r
        },
        _ => String::new(),
    };

    let t = match s.as_str() {
        "String" => "varchar".to_string(),
        "i32" => "int".to_string(),
        "i64" => "bigint".to_string(),
        "f32" => "float".to_string(),
        "f64" => "double".to_string(),
        "bool" => "bool".to_string(),
        _ => "varchar".to_string(),
    };

    t
}